/*
 *  modifier: Honrun
 *  date:     2021/12/21 20:42
 */
#include "stdio.h"
#include "stdint.h"
#include "DevicesMemPool.h"


/* 使x对n字节对齐 */
#define memPoolRoundUp(x, n)        (((x) + (n) - 1) & (~((n) - 1)))


/* 模拟内存池块大小 */
#define MEM_POOL_BLOCK_CAN_SIZE     (4 + 8 + 1)
/* 模拟内存池块数量 */
#define MEM_POOL_BLOCK_CAN0_COUNT   32
#define MEM_POOL_BLOCK_CAN1_COUNT   32


MemPoolType g_typeMemPoolCan0 = {0};
/* 需要增加 MEM_ROUNDUP_VALUE 个长度，以保证字节对齐 */
static uint8_t st_MemPoolBuffCan0[(MEM_POOL_BLOCK_CAN_SIZE * MEM_POOL_BLOCK_CAN0_COUNT) + sizeof(size_t)] = {0};

MemPoolType g_typeMemPoolCan1 = {0};
/* 需要增加 MEM_ROUNDUP_VALUE 个长度，以保证字节对齐 */
static uint8_t st_MemPoolBuffCan1[(MEM_POOL_BLOCK_CAN_SIZE * MEM_POOL_BLOCK_CAN1_COUNT) + sizeof(size_t)] = {0};


static int8_t cMemPoolCreate(MemPoolType *ptypeHead, void *pvMem, int32_t iBlockSize, int32_t iBlockCount)
{
    uint32_t uiAddr;

    if((ptypeHead == NULL) || (pvMem == NULL) || (iBlockSize < sizeof(MemPoolType)) || (iBlockCount < 1))
        return -1;

    ptypeHead->pNext = ptypeHead->pPre = ptypeHead;

    /* 分块，插入到空闲链表 */
    for(uiAddr = memPoolRoundUp((uint32_t)pvMem, sizeof(size_t)); iBlockCount > 0; --iBlockCount, uiAddr += iBlockSize)
    {
        vMemPoolFree(ptypeHead, (void *)uiAddr);
    }

    return 0;
}

void vMemPoolInit(void)
{
    cMemPoolCreate(&g_typeMemPoolCan0, st_MemPoolBuffCan0, MEM_POOL_BLOCK_CAN_SIZE, MEM_POOL_BLOCK_CAN0_COUNT);
    cMemPoolCreate(&g_typeMemPoolCan1, st_MemPoolBuffCan1, MEM_POOL_BLOCK_CAN_SIZE, MEM_POOL_BLOCK_CAN0_COUNT);
}

void *pvMemPoolMalloc(MemPoolType *ptypeHead)
{
    MemPoolType *ptypeNow;

    if((ptypeHead == NULL) || (ptypeHead->pNext == ptypeHead))
        return NULL;

    ptypeNow = ptypeHead->pNext;

    /* 释放空闲链表的第1个节点 */
    ptypeNow->pPre->pNext = ptypeNow->pNext;
    ptypeNow->pNext->pPre = ptypeNow->pPre;

    return ptypeNow;
}

void vMemPoolFree(MemPoolType *ptypeHead, void *pvMem)
{
    MemPoolType *ptypeNow = pvMem;

    if(pvMem != NULL)
    {
        /* 插入到空闲链表的最后 */
        ptypeNow->pPre          = ptypeHead->pPre;
        ptypeNow->pNext         = ptypeHead;
        ptypeHead->pPre->pNext  = ptypeNow;
        ptypeHead->pPre         = ptypeNow;
    }
}
